package com.example.kabaouser.controller;

import com.example.kabaouser.Utils.ResultVOUtil;
import com.example.kabaouser.VO.ResultVO;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("/es")
public class TestController {
    @Autowired
    private TransportClient client;

    @GetMapping("/get")
    @ResponseBody
    public ResponseEntity get(@RequestParam(name = "id",defaultValue = "") String id) {
        GetResponse result = this.client.prepareGet("people","man",id).get();

        if(id.isEmpty()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        if(!result.isExists()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity(result.getSource(),HttpStatus.OK);
    }

    @PostMapping("/add")
    @ResponseBody
    public ResponseEntity add(
            @RequestParam(name = "name") String name,
            @RequestParam(name = "country") String country,
            @RequestParam(name = "age") int age,
            @RequestParam(name = "date")
                    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
                    Date date
            ) {
        try {
            XContentBuilder contentBuilder = XContentFactory.jsonBuilder().startObject().field("name",name)
                    .field("country",country)
                    .field("age",age)
                    .field("date",date.getTime())
                    .endObject();
            IndexResponse response = this.client.prepareIndex("people","man")
                    .setSource(contentBuilder).get();
            return new ResponseEntity(response.getId(),HttpStatus.OK);
        }catch (IOException e){
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @DeleteMapping("/del")
    @ResponseBody
    public ResponseEntity delete(@RequestParam(name = "id",defaultValue = "") String id) {
        if(id.isEmpty()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        DeleteResponse response = this.client.prepareDelete("people","man",id).get();
        return new ResponseEntity(response.getResult().toString(),HttpStatus.OK);
    }

    @PostMapping("/upd")
    @ResponseBody
    public ResponseEntity updateTest(
            @RequestParam(name = "id",defaultValue = "") String id,
            @RequestParam(name = "name",defaultValue = "") String name,
            @RequestParam(name = "country",defaultValue = "") String country
    ) {
        if(id.isEmpty()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        System.out.println("id:" + id +" name: " + name + " country: " + country);
        UpdateRequest updateRequest = new UpdateRequest("people","man",id);
        try {
            XContentBuilder builder = XContentFactory.jsonBuilder()
                    .startObject();
            if(name != null) {
                builder.field("name",name);
            }
            if(country != null) {
                builder.field("country",country);
            }
            builder.endObject();
            updateRequest.doc(builder);
        }catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        try {
            UpdateResponse response = this.client.update(updateRequest).get();
            return new ResponseEntity(response.getResult().toString(),HttpStatus.OK);
        }catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/query")
    @ResponseBody
    public ResponseEntity query(@RequestParam(name = "name" ,required = false) String name,
                                @RequestParam(name = "gt_age" ,defaultValue = "0") int gtAge,
                                @RequestParam(name = "lt_age" , required = false) Integer ltAge) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(name != null) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("name",name));
        }
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").from(gtAge);
        if(ltAge != null && ltAge > 0) {
            rangeQueryBuilder.to(ltAge);
        }
        boolQueryBuilder.filter(rangeQueryBuilder);
        SearchRequestBuilder builder = this.client.prepareSearch("people").setTypes("man")
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(boolQueryBuilder).setFrom(0).setSize(10);
        System.out.println(boolQueryBuilder);
        SearchResponse response = builder.get();
        List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();
        for (SearchHit hit : response.getHits()) {
            result.add(hit.getSource());
        }
        return  new ResponseEntity(result,HttpStatus.OK);
    }

    @PostMapping("/ok")
    public ResultVO testOKhttp(@RequestParam(name = "name") String name,
                               @RequestParam(name = "age") String age,
                               HttpServletRequest request) {
        String token = request.getHeader("Access-User-Token");
        Map<String,String> map = new HashMap<String, String>();
        map.put("name",name);
        map.put("age",age);
        map.put("token",token);
        return ResultVOUtil.success(map);
    }
}